#define DLL_API _declspec(dllexport)
#include "strconverter.h"
#include <Windows.h>

#ifndef R_OK
#define R_OK 0
#endif

#ifndef R_ERROR
#define R_ERROR -1
#endif

//////////////////////////////////////////////////////////////////////////
int _stdcall ANSI2Unicode(IN const char* szAnsi, OUT wchar_t* szUnicode)
{
	if (NULL == szAnsi)
	{
		szUnicode = NULL;
		return R_OK;
	}

	int unicodeLen = ::MultiByteToWideChar(CP_ACP,0,szAnsi,-1,NULL,0); 
	if (NULL == szUnicode)
	{
		return unicodeLen;
	}

	if(0 == ::MultiByteToWideChar( CP_ACP,0, szAnsi, -1, (LPWSTR)szUnicode, unicodeLen))
	{
		return R_OK;
	}
	return R_ERROR; 
}

int _stdcall Unicode2ANSI(IN const wchar_t* szUnicode, OUT char* szAnsi)
{
	if (NULL == szUnicode)
	{
		szAnsi = NULL;
		return R_OK;
	}

	int ansiLen = ::WideCharToMultiByte( CP_ACP, 0, szUnicode, -1, NULL, 0, NULL, NULL );

	if (NULL == szAnsi)
	{
		return ansiLen;
	}

	if( 0 == ::WideCharToMultiByte( CP_ACP, 0, szUnicode, -1, szAnsi, ansiLen, NULL, NULL ))
	{
		return R_OK;
	}

	return R_ERROR;
}

int _stdcall UTF82Unicode(IN const char* szUtf8, OUT wchar_t* szUnicode )
{
	if (NULL == szUtf8)
	{
		szUnicode = NULL;
		return R_OK;
	}

	int unicodeLen = ::MultiByteToWideChar( CP_UTF8, 0, szUtf8, -1, NULL, 0 ); 
	if (NULL == szUnicode)
	{
		return unicodeLen;
	}

	if(0 == ::MultiByteToWideChar(CP_UTF8,0,szUtf8,-1,(LPWSTR)szUnicode,unicodeLen ))
	{
		return R_OK;
	}

	return R_ERROR; 
}

int _stdcall Unicode2UTF8( IN const wchar_t* szUnicode, OUT char *szUtf8 )
{
	if (NULL == szUnicode)
	{
		szUtf8 = NULL;
		return R_OK;
	}

	int utf8Len = WideCharToMultiByte( CP_UTF8, 0, szUnicode, -1, NULL, 0, NULL, NULL );
	if (NULL == szUtf8)
	{
		return utf8Len;
	}

	if ( 0 == ::WideCharToMultiByte( CP_UTF8, 0, szUnicode, -1,szUtf8, utf8Len, NULL, NULL ))
	{
		return R_OK;
	}
	return R_ERROR;
}

//////////////////////////////////////////////////////////////////////////
std::wstring _stdcall ANSI2Unicode(IN const std::string& strAnsi)
{
	int unicodeLen = ANSI2Unicode(strAnsi.c_str(), NULL);
	wchar_t* pUnicode = new wchar_t[unicodeLen];
	ANSI2Unicode(strAnsi.c_str(), pUnicode);
	std::wstring ws = std::wstring(pUnicode);
	delete []pUnicode;
	return ws;
}

std::string _stdcall Unicode2ANSI(IN const std::wstring& strUnicode)
{
	int ansiLen = Unicode2ANSI((wchar_t*)strUnicode.c_str(), NULL);
	char* pAnsi = new char[ansiLen];
	Unicode2ANSI((wchar_t*)strUnicode.c_str(), pAnsi);
	std::string s = std::string(pAnsi);
	delete []pAnsi;
	return s;
}


std::wstring _stdcall UTF82Unicode(IN const std::string& strUtf8)
{
	int unicodeLen = UTF82Unicode(strUtf8.c_str(), NULL);
	wchar_t* pUnicode = new wchar_t[unicodeLen];
	UTF82Unicode(strUtf8.c_str(), pUnicode);
	std::wstring ws = std::wstring(pUnicode);
	delete []pUnicode;
	return ws;
}

std::string _stdcall Unicode2UTF8(IN const std::wstring& strUnicode)
{
	int ansiLen = Unicode2UTF8((wchar_t*)strUnicode.c_str(), NULL);
	char* pAnsi = new char[ansiLen];
	Unicode2UTF8((wchar_t*)strUnicode.c_str(), pAnsi);
	std::string s = std::string(pAnsi);
	delete []pAnsi;
	return s;
}


//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

wchar_t* ANSIToUnicode(const char* szAnsi)
{
	int unicodeLen = ::MultiByteToWideChar(CP_ACP,0,szAnsi,-1,NULL,0 ); 
	wchar_t * pUnicode; 
	pUnicode = new wchar_t[unicodeLen+1]; 
	memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t)); 
	::MultiByteToWideChar( CP_ACP,0, szAnsi, -1, (LPWSTR)pUnicode, unicodeLen ); 
	return pUnicode; 
}

char* UnicodeToANSI( wchar_t* szUnicode )
{
	if ( !szUnicode )
	{
		return NULL;
	}

	char* pElementText;
	int iTextLen;

	// wide char to multi char 
	iTextLen = ::WideCharToMultiByte( CP_ACP, 0, szUnicode, -1, NULL, 0, NULL, NULL );
	pElementText = new char[iTextLen + 1];
	memset( pElementText, 0, iTextLen + 1);
	::WideCharToMultiByte( CP_ACP, 0, szUnicode, -1, pElementText, iTextLen, NULL, NULL );
	return pElementText;
}

wchar_t* UTF8ToUnicode( const char* szUtf8 )
{
	int len = 0;
	len = strlen( szUtf8 );
	int unicodeLen = ::MultiByteToWideChar( CP_UTF8, 0, szUtf8, -1, NULL, 0 ); 
	wchar_t * pUnicode; 
	pUnicode = new wchar_t[ unicodeLen + 1 ]; 
	memset( pUnicode, 0, (unicodeLen + 1 ) * 2 ); 
	::MultiByteToWideChar( CP_UTF8,0,szUtf8,-1,(LPWSTR)pUnicode,unicodeLen ); 
	return pUnicode; 
}

char* UnicodeToUTF8( const wchar_t* szUnicode )
{
	char* pElementText;
	int iTextLen;

	// wide char to multi char 
	iTextLen = WideCharToMultiByte( CP_UTF8, 0, szUnicode, -1, NULL, 0, NULL, NULL );
	pElementText = new char[iTextLen + 1];
	memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
	::WideCharToMultiByte( CP_UTF8, 0, szUnicode, -1,pElementText, iTextLen, NULL, NULL );
	return pElementText;
}
